from ma.commons.core.constants import MAP, REDUCE
from ma.fs.dfs.dfsflags import *
from ma.const import *
from exceptions import *
#from constants import *
import ma.log

class TaskScheduler(object):
     
    """this is the scheduler that guides an NT as to which task of which job to pick up
    in case it has capacity to pick up more tasks
    """
    
    def __init__(self, job_dict):
        
        """this function will build up the jobs list that is consulted while 
        scheduling tasks for an NT; basic principle of scheduling is round robin 
        between jobs and to assign maps and reduces per job in the ratio 
        total-maps/total-reduces
        """
        self.__log = ma.log.get_logger("ma.mapred")
        
        #also have an iterator over the dict that can persistently mark 
        #the last job from which a task was scheduled 
        self.iterator = iter(job_dict.keys())
        
        if len(job_dict)>0:
            #to persist the current iterator value
            self.job_id = next(self.iterator)
            #extracting job data
            self.job_data = job_dict[self.job_id]
        else:
            self.job_data = None
        
        self.iterator = None
    
        
    def scheduleTasks(self, job_dict):
        
        """this function will return a list of suggested reduce or map tasks of a job for the NT to run;
        basic principle of scheduling is round robin between jobs and to first all maps and then the reduces
        as the maps finish
        """
        self.__log.info('Fetching list of maps or reduces for scheduling task')
        #in case job_dict is not empty
          
        if self.job_data != None:
            
            prev_job_id = self.job_id
            #to assign an iterator to the dict and point it to the first job
            self.iterator = iter(job_dict.keys())
            self.job_id = next(self.iterator)
            
            #try to get to last scheduled jobs position
            for j in range(0, len(job_dict)):
                if prev_job_id == self.job_id:
                    break
                else:
                    try:
                        self.job_id = next(self.iterator)
                    except StopIteration:
                        break
            
            #increment to the next job in the dict. if job dict cannot be iterated then move to head of dict    
            try:
                self.job_id = next(self.iterator)
            except StopIteration:
                self.iterator = iter(job_dict.keys())
                self.job_id = next(self.iterator)
            
            self.iterator = None
            #extract job_id    
            self.job_data = job_dict[self.job_id]     
    
            if self.job_data[0] == False:
                print(self.job_id, MAP)
                return self.job_id, MAP
            else:
                print(self.job_id, REDUCE)
                return self.job_id, REDUCE

    

'''
def main(argv=None):
    
    print "TS started"
    d = {1:['False'],0:['True'],2:['False']}
    ts = TaskScheduler(d)
    
    for i in range(0,10):
        ts.scheduleATask(d)
        
if __name__ == "__main__":

    """The program's entry point."""
    sys.exit(main())    
'''   
